import { cert } from '@kit.DeviceCertificateKit';
import { util } from '@kit.ArkTS';
import { http } from '@kit.NetworkKit';

/**
 * NetworkClientCertAdapter 接口定义了与网络客户端证书相关的适配器方法。
 * 该适配器用于获取不同类型的证书，包括CA证书和客户端证书。
 */
export interface NetworkClientCertAdapter {

  /**
   * 根据主机名获取CA证书。
   * @param host 主机名，用于查找对应的CA证书。
   * @returns 返回对应主机名的CA证书的字符串表示，如果找不到则返回undefined。
   */
  getCACertBy(host: string): string | undefined

  /**
   * 根据主机名获取客户端证书。
   * @param host 主机名，用于查找对应的客户端证书。
   * @returns 返回对应主机名的客户端证书对象（http.ClientCert），如果找不到则返回undefined。
   */
  getClientCertBy(host: string): http.ClientCert | undefined

  /**
   * 获取所有证书。
   * @returns 返回一个包含所有X509证书的数组，如果没有任何证书则返回undefined。
   */
  getCerts(): cert.X509Cert[] | undefined
}

export class NetworkClientCertManager {
  // 证书适配器
  private static certAdapter: NetworkClientCertAdapter

  checkServerTrusted(X509Certificate: cert.X509Cert): void {
    // 时间校验成功的设置值
    let now = new Date();
    let year = now.getUTCFullYear();
    let month = ('0' + (now.getUTCMonth() + 1)).slice(-2);
    let day = ('0' + now.getUTCDate()).slice(-2);
    let hours = ('0' + now.getUTCHours()).slice(-2);
    let minutes = ('0' + now.getUTCMinutes()).slice(-2);
    let seconds = ('0' + now.getUTCSeconds()).slice(-2);
    let date = year + month + day + hours + minutes + seconds + 'Z';
    try {
      X509Certificate.checkValidityWithDate(date); // 检查X509证书有效期
    } catch (error) {
      error.message = '[Network]checkValidityWithDate failed, errCode: ' + error.code + ', errMsg: ' + error.message;
      throw new Error(error);
    }
  }

  checkClientTrusted(X509Certificate: cert.X509Cert): void {
    let publicKey = X509Certificate.getPublicKey(); // 获取X509证书公钥
    console.log(`[Network]X509证书公钥1:${JSON.stringify(publicKey)}`)
    let pubKey = X509Certificate.getItem(cert.CertItemType.CERT_ITEM_TYPE_PUBLIC_KEY); // 获取X509证书公钥.
    let utf8 = util.TextDecoder.create().decodeWithStream(pubKey.data);
    console.log(`[Network]X509证书公钥2:${utf8}`)
  }

  /**
   * 注册一个网络客户端证书适配器。
   * @param adapter 一个实现了NetworkClientCertAdapter接口的对象，用于管理客户端证书。
   */
  static register(adapter: NetworkClientCertAdapter) {
    NetworkClientCertManager.certAdapter = adapter
  }

  /**
   * 根据主机名获取CA证书。
   * @param host 请求的主机名，默认为空字符串。
   * @returns 返回对应主机名的CA证书，如果找不到或未设置适配器，则返回undefined。
   */
  getCACertBy(host: string = ''): string | undefined {
    if (!NetworkClientCertManager.certAdapter) {
      return undefined
    }
    return NetworkClientCertManager.certAdapter.getCACertBy(host)
  }

  /**
   * 根据主机名获取客户端证书。
   * @param host 请求的主机名，默认为空字符串。
   * @returns 返回对应主机名的客户端证书，如果找不到或未设置适配器，则返回undefined。
   */
  getClientCertBy(host: string = ''): http.ClientCert | undefined {
    if (!NetworkClientCertManager.certAdapter) {
      return undefined
    }
    return NetworkClientCertManager.certAdapter.getClientCertBy(host)
  }

  /**
   * 获取所有证书。
   * @returns 返回所有证书的数组，如果未设置适配器，则返回undefined。
   */

  getCerts(): cert.X509Cert[] | undefined {
    if (!NetworkClientCertManager.certAdapter) {
      return undefined
    }
    return NetworkClientCertManager.certAdapter.getCerts()
  }
}